/**********************************************************
 * Copyright © 2024 Walkline Wang (https://walkline.wang)
 * Gitee: https://gitee.com/walkline/keypad-for-ops
 **********************************************************/
#include "74hc165.h"

SPIClass SPI_1(KEYS_MOSI, KEYS_MISO, KEYS_CLK);

void _74HC165::setup() {
#if DEBUG_PROMPT
    Serial.println("74HC165 Setup");
#endif

    memset(key_buffer, 0xff, IO_COUNT / 8);

    pinMode(KEYS_CLK, OUTPUT);
    pinMode(KEYS_PL, OUTPUT);
    pinMode(KEYS_CE, OUTPUT);

    digitalWrite(KEYS_CLK, HIGH);
    digitalWrite(KEYS_PL, HIGH);
    digitalWrite(KEYS_CE, LOW);

    SPI_1.begin();
    SPI_1.setBitOrder(LSBFIRST);
    SPI_1.setClockDivider(SPI_CLOCK_DIV4);
}

void _74HC165::get_keys_status() {
    uint8_t mask;
    uint8_t buffer_1[IO_COUNT / 8] = {};
    uint8_t buffer_2[IO_COUNT / 8] = {};

    scan_keys(buffer_1);
    delayMicroseconds(KEYS_FILTER_TIME);
    scan_keys(buffer_2);

    for (uint8_t count = 0; count < IO_COUNT / 8; count++) {
        mask = buffer_1[count] ^ buffer_2[count];
        buffer_2[count] |= mask;
    }

    if (memcmp(buffer_2, key_buffer, sizeof(key_buffer)) != 0) {
        memcpy(key_buffer, buffer_2, sizeof(key_buffer));

#if DEBUG_DATA
        /* LSB Format */
        Serial.print("\nKey Buffer: ");
        for (int16_t count = IO_COUNT / 8 - 1; count >= 0; count--) {
            Serial.print(key_buffer[count], BIN);
            Serial.print(" ");
        }
        Serial.println();
#endif
    }
}

void _74HC165::scan_keys(uint8_t *buffer) {
    memset(buffer, 0xff, IO_COUNT / 8);

    digitalWrite(KEYS_PL, LOW);  /* 并行读取数据 */
    digitalWrite(KEYS_PL, HIGH); /* 停止读取数据 */

    SPI_1.transfer(buffer, IO_COUNT / 8);
}
